package de.bomzhi.mz.pflection.problem;

import java.util.ArrayList;
import java.util.List;

import com.powerflasher.fdt.core.dom.CommonRoot;
import com.powerflasher.fdt.core.dom.IBasicFunctionDeclaration;
import com.powerflasher.fdt.core.dom.IName;
import com.powerflasher.fdt.core.dom.INode;
import com.powerflasher.fdt.core.outermodel.IFunctionModel;
import com.powerflasher.fdt.core.outermodel.IMasterModel;
import com.powerflasher.fdt.core.outermodel.IOuterModelElement;
import com.powerflasher.fdt.core.outermodel.IOuterModelVisitor;
import com.powerflasher.fdt.core.outermodel.ProjectModel;
import com.powerflasher.fdt.core.parser.ICompilationUnit;
import com.powerflasher.fdt.core.problems2.IProblem;
import com.powerflasher.fdt.core.problems2.IProblemFactory;
import com.powerflasher.fdt.core.problems2.IProblemGenerator;
import com.powerflasher.fdt.core.problems2.IProblemStates;

import de.bomzhi.mz.pflection.FDTPflection;
import de.bomzhi.mz.pflection.model.PflectionValuesComputer;
import de.bomzhi.mz.pflection.preferences.PreferenceConstants;

public class MlocProblemGenerator implements IProblemGenerator {

	private static final String MLOC_ID = "de.bomzhi.pflection.problems.mloc";

	private final class MlocCounter implements
			IOuterModelVisitor {


		private List<INode> problemNodes = new ArrayList<INode>();

		@Override
		public boolean visitLeave(IOuterModelElement arg0) {
			return false;
		}

		@Override
		public boolean visitEnter(IOuterModelElement element) {
			if(element instanceof IFunctionModel){
				IFunctionModel funcModel = (IFunctionModel)element;
				int mloc = PflectionValuesComputer.computeMLOC(funcModel);
				if(mloc>higherBound()){
					IBasicFunctionDeclaration func = (IBasicFunctionDeclaration) funcModel.getSource();
					IName declarationName = func.getDeclarationName();
					if(declarationName!=null){
						problemNodes.add(declarationName);
					}else{
						problemNodes.add(func);
					}
				}
			}
			return true;
		}
		public List<INode> getProblemNodes() {
			return problemNodes;
		}
	}

	public MlocProblemGenerator() {
	}

	private int higherBound() {
		return FDTPflection.getDefault().getPreferenceStore().getInt(PreferenceConstants.P_MLOC);
	}

	@Override
	public List<IProblem> generateProblems(ICompilationUnit cu,
			IProblemStates states, IProblemFactory problemFactory, ProjectModel arg3) {
		List<IProblem> problems = new ArrayList<IProblem>();
		CommonRoot ast = cu.getAST();
		if(ast==null){
			return problems;
		}
		IMasterModel masterModel = ast.getMasterModel();
		MlocCounter mlocCounter = new MlocCounter();
		masterModel.accept(mlocCounter);
		for (INode node : mlocCounter.getProblemNodes()) {
			IProblem problem = problemFactory.createProblem(MLOC_ID, states, node, "The MLOC count of this function is higher than ${0}", ""+higherBound());
			problems.add(problem);
		}
		return problems;
	}

}
